{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "fce539cc-440f-418c-8991-fbaf9196be93",
   "metadata": {},
   "source": [
    "# Lesson 4: Deploy an AWS Lambda function"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "81d4b464-256d-446d-9910-5523a810659b",
   "metadata": {
    "tags": []
   },
   "source": [
    "### Import all needed packages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a43fa83e",
   "metadata": {
    "height": 30
   },
   "outputs": [],
   "source": [
    "import boto3, os"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "90d0cccb-ee62-4a8f-8672-0d6213cca069",
   "metadata": {
    "height": 63
   },
   "outputs": [],
   "source": [
    "from helpers.Lambda_Helper import Lambda_Helper\n",
    "from helpers.S3_Helper import S3_Helper\n",
    "from helpers.Display_Helper import Display_Helper"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0115c012",
   "metadata": {
    "height": 63
   },
   "outputs": [],
   "source": [
    "lambda_helper = Lambda_Helper()\n",
    "# deploy_function\n",
    "# add_lambda_trigger"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d9785005",
   "metadata": {
    "height": 80
   },
   "outputs": [],
   "source": [
    "s3_helper = S3_Helper()\n",
    "# upload_file\n",
    "# download_object \n",
    "# list_objects"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8f93593c",
   "metadata": {
    "height": 63
   },
   "outputs": [],
   "source": [
    "display_helper = Display_Helper()\n",
    "# text_file\n",
    "# json_file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f33a0909-99c0-4fd8-9d0c-753d12dd4045",
   "metadata": {
    "height": 29
   },
   "outputs": [],
   "source": [
    "bucket_name_text = os.environ['LEARNERS3BUCKETNAMETEXT']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ce1dc532",
   "metadata": {
    "height": 539
   },
   "outputs": [],
   "source": [
    "%%writefile prompt_template.txt\n",
    "I need to summarize a conversation. The transcript of the conversation is between the <data> XML like tags.\n",
    "\n",
    "<data>\n",
    "{{transcript}}\n",
    "</data>\n",
    "\n",
    "The summary must contain a one word sentiment analysis, and a list of issues, problems or causes of friction\n",
    "during the conversation. The output must be provided in JSON format shown in the following example. \n",
    "\n",
    "Example output:\n",
    "{\n",
    "    \"version\": 0.1,\n",
    "    \"sentiment\": <sentiment>,\n",
    "    \"issues\": [\n",
    "        {\n",
    "            \"topic\": <topic>,\n",
    "            \"summary\": <issue_summary>,\n",
    "        }\n",
    "    ]\n",
    "}\n",
    "\n",
    "An `issue_summary` must only be one of:\n",
    "{%- for topic in topics %}\n",
    " - `{{topic}}`\n",
    "{% endfor %}\n",
    "\n",
    "Write the JSON output and nothing more.\n",
    "\n",
    "Here is the JSON output:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "680d354d",
   "metadata": {
    "height": 29
   },
   "outputs": [],
   "source": [
    "display_helper.text_file('prompt_template.txt')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a4acb14e-ca71-49fa-923b-ca180c8e2eaa",
   "metadata": {},
   "source": [
    "### Create the Lambda function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "df062c80",
   "metadata": {
    "height": 2222
   },
   "outputs": [],
   "source": [
    "%%writefile lambda_function.py\n",
    "\n",
    "\n",
    "#############################################################\n",
    "#\n",
    "# This Lambda function is written to a file by the notebook \n",
    "# It does not run in the notebook!\n",
    "#\n",
    "#############################################################\n",
    "\n",
    "import boto3\n",
    "import json \n",
    "from jinja2 import Template\n",
    "\n",
    "s3_client = boto3.client('s3')\n",
    "bedrock_runtime = boto3.client('bedrock-runtime', 'us-west-2')\n",
    "\n",
    "def lambda_handler(event, context):\n",
    "    \n",
    "    bucket = event['Records'][0]['s3']['bucket']['name']\n",
    "    key = event['Records'][0]['s3']['object']['key']\n",
    "    \n",
    "    # One of a few different checks to ensure we don't end up in a recursive loop.\n",
    "    if \"-transcript.json\" not in key: \n",
    "        print(\"This demo only works with *-transcript.json.\")\n",
    "        return\n",
    "    \n",
    "    try: \n",
    "        file_content = \"\"\n",
    "        \n",
    "        response = s3_client.get_object(Bucket=bucket, Key=key)\n",
    "        \n",
    "        file_content = response['Body'].read().decode('utf-8')\n",
    "        \n",
    "        transcript = extract_transcript_from_textract(file_content)\n",
    "\n",
    "        print(f\"Successfully read file {key} from bucket {bucket}.\")\n",
    "\n",
    "        print(f\"Transcript: {transcript}\")\n",
    "        \n",
    "        summary = bedrock_summarisation(transcript)\n",
    "        \n",
    "        s3_client.put_object(\n",
    "            Bucket=bucket,\n",
    "            Key='results.txt',\n",
    "            Body=summary,\n",
    "            ContentType='text/plain'\n",
    "        )\n",
    "        \n",
    "    except Exception as e:\n",
    "        print(f\"Error occurred: {e}\")\n",
    "        return {\n",
    "            'statusCode': 500,\n",
    "            'body': json.dumps(f\"Error occurred: {e}\")\n",
    "        }\n",
    "\n",
    "    return {\n",
    "        'statusCode': 200,\n",
    "        'body': json.dumps(f\"Successfully summarized {key} from bucket {bucket}. Summary: {summary}\")\n",
    "    }\n",
    "        \n",
    "        \n",
    "        \n",
    "def extract_transcript_from_textract(file_content):\n",
    "\n",
    "    transcript_json = json.loads(file_content)\n",
    "\n",
    "    output_text = \"\"\n",
    "    current_speaker = None\n",
    "\n",
    "    items = transcript_json['results']['items']\n",
    "\n",
    "    # Iterate through the content word by word:\n",
    "    for item in items:\n",
    "        speaker_label = item.get('speaker_label', None)\n",
    "        content = item['alternatives'][0]['content']\n",
    "        \n",
    "        # Start the line with the speaker label:\n",
    "        if speaker_label is not None and speaker_label != current_speaker:\n",
    "            current_speaker = speaker_label\n",
    "            output_text += f\"\\n{current_speaker}: \"\n",
    "        \n",
    "        # Add the speech content:\n",
    "        if item['type'] == 'punctuation':\n",
    "            output_text = output_text.rstrip()  # Remove the last space\n",
    "        \n",
    "        output_text += f\"{content} \"\n",
    "        \n",
    "    return output_text\n",
    "        \n",
    "\n",
    "def bedrock_summarisation(transcript):\n",
    "    \n",
    "    with open('prompt_template.txt', \"r\") as file:\n",
    "        template_string = file.read()\n",
    "\n",
    "    data = {\n",
    "        'transcript': transcript,\n",
    "        'topics': ['charges', 'location', 'availability']\n",
    "    }\n",
    "    \n",
    "    template = Template(template_string)\n",
    "    prompt = template.render(data)\n",
    "    \n",
    "    print(prompt)\n",
    "    \n",
    "    kwargs = {\n",
    "        \"modelId\": \"amazon.titan-text-express-v1\",\n",
    "        \"contentType\": \"application/json\",\n",
    "        \"accept\": \"*/*\",\n",
    "        \"body\": json.dumps(\n",
    "            {\n",
    "                \"inputText\": prompt,\n",
    "                \"textGenerationConfig\": {\n",
    "                    \"maxTokenCount\": 2048,\n",
    "                    \"stopSequences\": [],\n",
    "                    \"temperature\": 0,\n",
    "                    \"topP\": 0.9\n",
    "                }\n",
    "            }\n",
    "        )\n",
    "    }\n",
    "    \n",
    "    response = bedrock_runtime.invoke_model(**kwargs)\n",
    "\n",
    "    summary = json.loads(response.get('body').read()).get('results')[0].get('outputText')    \n",
    "    return summary\n",
    "    \n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "75deb539",
   "metadata": {
    "height": 80
   },
   "outputs": [],
   "source": [
    "lambda_helper.deploy_function(\n",
    "    [\"lambda_function.py\", \"prompt_template.txt\"],\n",
    "    function_name=\"LambdaFunctionSummarize\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3676e124",
   "metadata": {
    "height": 46
   },
   "outputs": [],
   "source": [
    "lambda_helper.filter_rules_suffix = \"json\"\n",
    "lambda_helper.add_lambda_trigger(bucket_name_text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "872cf2b4",
   "metadata": {
    "height": 29
   },
   "outputs": [],
   "source": [
    "# display_helper.json_file('demo-transcript.json')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d8d9cd84",
   "metadata": {
    "height": 29
   },
   "outputs": [],
   "source": [
    "s3_helper.upload_file(bucket_name_text, 'demo-transcript.json')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2ea8c684-9250-4682-b819-f01d2325bd46",
   "metadata": {},
   "source": [
    "#### Restart kernel if needed.\n",
    "- If you run the code fairly quickly from start to finish, it's possible that the following code cell `s3_helper.list_objects(bucket_name_text)` will give a \"Not Found\" error.  \n",
    "- If waiting a few seconds (10 seconds) and re-running this cell does not resolve the error, then you can restart the kernel of the jupyter notebook.\n",
    "- Go to menu->Kernel->Restart Kernel.\n",
    "- Then run the code cells from the start of the notebook, waiting 2 seconds or so for each code cell to finish executing."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4585029c",
   "metadata": {
    "height": 29
   },
   "outputs": [],
   "source": [
    "s3_helper.list_objects(bucket_name_text)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01ee10b9-9c52-4a2a-8207-fc3c6ad21a8d",
   "metadata": {},
   "source": [
    "#### Re-run \"download\" code cell as needed\n",
    "- It may take a few seconds for the results to be generated.\n",
    "- If you see a `Not Found` error, please wait a few seconds and then try running the `s3_helper.download_object` again."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "55d70063",
   "metadata": {
    "height": 29
   },
   "outputs": [],
   "source": [
    "s3_helper.download_object(bucket_name_text, \"results.txt\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c3b4e625",
   "metadata": {
    "height": 29
   },
   "outputs": [],
   "source": [
    "display_helper.text_file('results.txt')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
